<!DOCTYPE html>
<html lang="en">

<!-- Head tag -->
<head><meta name="generator" content="Hexo 3.8.0">

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!--Description-->

    

    
        <meta name="description" content="AVCaptureSessionAVCaptureSession是AVFoundation捕捉栈的核心类。一个session相当于一个虚拟的”插线板”，用于连接输入和输出资源。捕捉会话被处理从物理设备得到的数据流，比如摄像头和麦克风设备，输出到一个或多个目的地。可以动态地配置输入和输出的线路，让开发">
    

    <!--Author-->
    
        <meta name="author" content="Cyrus">
    

    <!--Open Graph Title-->
    
        <meta property="og:title" content="AVFoundation学习笔记九 AVCaptureSession1">
    

    <!--Open Graph Description-->
    
        <meta property="og:description" content="AVCaptureSessionAVCaptureSession是AVFoundation捕捉栈的核心类。一个session相当于一个虚拟的”插线板”，用于连接输入和输出资源。捕捉会话被处理从物理设备得到的数据流，比如摄像头和麦克风设备，输出到一个或多个目的地。可以动态地配置输入和输出的线路，让开发">
    

    <!--Open Graph Site Name-->
        <meta property="og:site_name" content="Cyrus的技术空间">

    <!--Type page-->
    
        <meta property="og:type" content="article">
    

    <!--Page Cover-->
    
    
        <meta property="og:image" content="http://cyrus_huang.gitee.io/bloghttp://www.codeblocq.com/assets/projects/hexo-theme-clean-blog/img/home-bg.jpg">
    

        <meta name="twitter:card" content="summary_large_image">

    

    
        <meta name="twitter:image" content="http://cyrus_huang.gitee.io/bloghttp://www.codeblocq.com/assets/projects/hexo-theme-clean-blog/img/home-bg.jpg">
    

    <!-- Title -->
    
    <title>AVFoundation学习笔记九 AVCaptureSession1 - Cyrus的技术空间</title>

    <!-- Bootstrap Core CSS -->
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom CSS -->
    <link rel="stylesheet" href="/blog/css/style.css">

    <!-- Custom Fonts -->
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    <link href="//fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel="stylesheet" type="text/css">
    <link href="//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- Gallery -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.css" type="text/css" rel="stylesheet">

    <!-- Google Analytics -->
    


    <!-- favicon -->
    

</head>


<body>

    <!-- Menu -->
    <!-- Navigation -->
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header page-scroll">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/blog/">Cyrus的技术空间</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav navbar-right">
                
                    <li>
                        <a href="/blog/">
                            
                                Home
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="/blog/archives">
                            
                                Archives
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="/blog/tags">
                            
                                Tags
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="/blog/categories">
                            
                                Categories
                            
                        </a>
                    </li>
                
                    <li>
                        <a href="https://github.com/klugjo/hexo-theme-clean-blog">
                            
                                <i class="fa fa-github fa-stack-2x"></i>
                            
                        </a>
                    </li>
                
            </ul>
        </div>
        <!-- /.navbar-collapse -->
    </div>
    <!-- /.container -->
</nav>

    <!-- Main Content -->
    <!-- Page Header -->
<!-- Set your background image for this header in your post front-matter: cover -->

<header class="intro-header" style="background-image: url('http://www.codeblocq.com/assets/projects/hexo-theme-clean-blog/img/home-bg.jpg')">
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <div class="post-heading">
                    <h1>AVFoundation学习笔记九 AVCaptureSession1</h1>
                    
                    <span class="meta">
                        <!-- Date and Author -->
                        
                            Posted by Cyrus on
                        
                        
                            2018-11-12
                        
                    </span>
                </div>
            </div>
        </div>
    </div>
</header>

<!-- Post Content -->
<article>
    <div class="container">
        <div class="row">

            <!-- Tags and categories -->
           
                <div class="col-lg-4 col-lg-offset-2 col-md-5 col-md-offset-1 post-tags">
                    
                        

<a href="/blog/categories/AVFoundation/">AVFoundation</a>

                    
                </div>
                <div class="col-lg-4 col-md-5 post-categories">
                    
                </div>
            

            <!-- Gallery -->
            

            <!-- Post Main Content -->
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <p><img src="http://cyrus_huang.gitee.io/blog/2018/11/12/AVFoundation学习笔记九/capture_session1.png" alt=""></p>
<h3 id="AVCaptureSession"><a href="#AVCaptureSession" class="headerlink" title="AVCaptureSession"></a>AVCaptureSession</h3><p>AVCaptureSession是AVFoundation捕捉栈的核心类。一个session相当于一个虚拟的”插线板”，用于连接输入和输出资源。捕捉会话被处理从物理设备得到的数据流，比如摄像头和麦克风设备，输出到一个或多个目的地。可以动态地配置输入和输出的线路，让开发者能够在会话进行中按需重新配置捕捉环境。</p>
<p>session还可以额外配置一个会话预设值（session preset）,用来控制捕捉数据的格式和质量。会话预设值默认为AVCaptureSessionPresetHigh,它适用于大多数情况。</p>
<h3 id="AVCaptureDevice"><a href="#AVCaptureDevice" class="headerlink" title="AVCaptureDevice"></a>AVCaptureDevice</h3><p>AVCaptureDevice为诸如摄像头或麦克风等物理设备定义了一个接口。AVCaptureDevice针对物理硬件设备定义了大量的控制方法，比如控制摄像头的对焦、曝光、白平衡和闪光灯等。<br>AVCaptureDevice定义了大量类方法用于访问系统的捕捉设备，最常用的一个方法是defaultDeviceWithMediaType:,它会根据给定的媒体类型返回一个系统指定的默认设备。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">+ (NSArray&lt;AVCaptureDevice *&gt; *)devicesWithMediaType:(AVMediaType)mediaType</span><br><span class="line">+ (nullable AVCaptureDevice *)defaultDeviceWithMediaType:(AVMediaType)mediaType;</span><br></pre></td></tr></table></figure></p>
<h3 id="AVCaptureDeviceInput"><a href="#AVCaptureDeviceInput" class="headerlink" title="AVCaptureDeviceInput"></a>AVCaptureDeviceInput</h3><p>在使用捕捉设备进行处理前，需要将它添加为session的输入。不过一个captureDevice不能直接添加到captureSession中，需要将它封装到一个AVCaptureDeviceInput实例来添加。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">+ (nullable instancetype)deviceInputWithDevice:(AVCaptureDevice *)device error:(NSError * _Nullable * _Nullable)outError;</span><br></pre></td></tr></table></figure></p>
<h3 id="AVCaptureOutput"><a href="#AVCaptureOutput" class="headerlink" title="AVCaptureOutput"></a>AVCaptureOutput</h3><p>AVFoundation定义了AVCaptureOutput的许多扩展类。AVCaptureOutput是一个抽象基类，用于为从捕捉会话得到的数据寻找输出目的地。框架定义了一些高级扩展类，如：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">AVCaptureStillImageOutput:捕捉静态照片</span><br><span class="line">AVCaptureMovieFileOutput: 捕捉视频</span><br><span class="line">AVCaptureAudioDataOutput: 捕捉底层音频数据</span><br><span class="line">AVCaptureVideoDataOutput: 捕捉底层视频数据</span><br></pre></td></tr></table></figure></p>
<h3 id="AVCaptureConnection"><a href="#AVCaptureConnection" class="headerlink" title="AVCaptureConnection"></a>AVCaptureConnection</h3><p>session首先需要确定由给定captureInput渲染的媒体类型，并自动建立其到能够接收该媒体类型的captureOutput的连接.比如AVCaptureMovieFileOutput可以授受音频和视频数据，所以会话会确定哪些输入产生视频，哪些输入产生音频，正确地建立该连接。</p>
<h3 id="AVCaptureVideoPreviewLayer"><a href="#AVCaptureVideoPreviewLayer" class="headerlink" title="AVCaptureVideoPreviewLayer"></a>AVCaptureVideoPreviewLayer</h3><p>AVCaptureVideoPreviewLayer展示正在捕捉的场景。previewLayer是一个Core Animation的CALayer子类，对捕捉视频数据进行实时预览。</p>
<p>代码：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">//创建session和输入输出</span><br><span class="line">self.captureSession = [[AVCaptureSession alloc] init];                  // 1</span><br><span class="line">    self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;</span><br><span class="line"> 	// Set up default camera device</span><br><span class="line"> 	AVCaptureDevice *videoDevice =                                          // 2</span><br><span class="line">        [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];</span><br><span class="line">    AVCaptureDeviceInput *videoInput =                                      // 3</span><br><span class="line">        [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:error];</span><br><span class="line">    if (videoInput) &#123;</span><br><span class="line">        if ([self.captureSession canAddInput:videoInput]) &#123;                 // 4</span><br><span class="line">            [self.captureSession addInput:videoInput];</span><br><span class="line">            self.activeVideoInput = videoInput;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        return NO;</span><br><span class="line">    &#125;</span><br><span class="line">    // Setup default microphone</span><br><span class="line">    AVCaptureDevice *audioDevice =                                          // 5</span><br><span class="line">        [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];</span><br><span class="line">    AVCaptureDeviceInput *audioInput =                                      // 6</span><br><span class="line">        [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:error];</span><br><span class="line">    if (audioInput) &#123;</span><br><span class="line">        if ([self.captureSession canAddInput:audioInput]) &#123;                 // 7</span><br><span class="line">            [self.captureSession addInput:audioInput];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        return NO;</span><br><span class="line">    &#125;</span><br><span class="line"> 	// Setup the still image output</span><br><span class="line">    self.imageOutput = [[AVCaptureStillImageOutput alloc] init];            // 8</span><br><span class="line">    self.imageOutput.outputSettings = @&#123;AVVideoCodecKey : AVVideoCodecJPEG&#125;;</span><br><span class="line"> 	if ([self.captureSession canAddOutput:self.imageOutput]) &#123;</span><br><span class="line"> 		[self.captureSession addOutput:self.imageOutput];</span><br><span class="line"> 	&#125;</span><br><span class="line">    return YES;</span><br></pre></td></tr></table></figure></p>
<p>切换摄像头<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">- (AVCaptureDevice *)activeCamera &#123;                                         // 3</span><br><span class="line">    return self.activeVideoInput.device;</span><br><span class="line">&#125;</span><br><span class="line">- (AVCaptureDevice *)inactiveCamera &#123;                                       // 4</span><br><span class="line">    AVCaptureDevice *device = nil;</span><br><span class="line">    if (self.cameraCount &gt; 1) &#123;</span><br><span class="line">        if ([self activeCamera].position == AVCaptureDevicePositionBack) &#123;  // 5</span><br><span class="line">            device = [self cameraWithPosition:AVCaptureDevicePositionFront];</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            device = [self cameraWithPosition:AVCaptureDevicePositionBack];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return device;</span><br><span class="line">&#125;</span><br><span class="line">- (BOOL)canSwitchCameras &#123;                                                  // 6</span><br><span class="line">    return self.cameraCount &gt; 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (BOOL)switchCameras &#123;</span><br><span class="line">    if (![self canSwitchCameras]) &#123;                                         // 1</span><br><span class="line">        return NO;</span><br><span class="line">    &#125;</span><br><span class="line">    NSError *error;</span><br><span class="line">    AVCaptureDevice *videoDevice = [self inactiveCamera];                   // 2</span><br><span class="line">    AVCaptureDeviceInput *videoInput =</span><br><span class="line">    [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&amp;error];</span><br><span class="line">    if (videoInput) &#123;</span><br><span class="line">        [self.captureSession beginConfiguration];                           // 3</span><br><span class="line">        [self.captureSession removeInput:self.activeVideoInput];            // 4</span><br><span class="line">        if ([self.captureSession canAddInput:videoInput]) &#123;                 // 5</span><br><span class="line">            [self.captureSession addInput:videoInput];</span><br><span class="line">            self.activeVideoInput = videoInput;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            [self.captureSession addInput:self.activeVideoInput];</span><br><span class="line">        &#125;</span><br><span class="line">        [self.captureSession commitConfiguration];                          // 6</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        [self.delegate deviceConfigurationFailedWithError:error];           // 7</span><br><span class="line">        return NO;</span><br><span class="line">    &#125;</span><br><span class="line">    return YES;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>闪光灯<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">- (BOOL)cameraHasFlash &#123;</span><br><span class="line">    return [[self activeCamera] hasFlash];</span><br><span class="line">&#125;</span><br><span class="line">- (AVCaptureFlashMode)flashMode &#123;</span><br><span class="line">    return [[self activeCamera] flashMode];</span><br><span class="line">&#125;</span><br><span class="line">- (void)setFlashMode:(AVCaptureFlashMode)flashMode &#123;</span><br><span class="line">    AVCaptureDevice *device = [self activeCamera];</span><br><span class="line">    if (device.flashMode != flashMode &amp;&amp;</span><br><span class="line">        [device isFlashModeSupported:flashMode]) &#123;</span><br><span class="line">        NSError *error;</span><br><span class="line">        if ([device lockForConfiguration:&amp;error]) &#123;</span><br><span class="line">            device.flashMode = flashMode;</span><br><span class="line">            [device unlockForConfiguration];</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            [self.delegate deviceConfigurationFailedWithError:error];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>手电筒<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">- (BOOL)cameraHasTorch &#123;</span><br><span class="line">    return [[self activeCamera] hasTorch];</span><br><span class="line">&#125;</span><br><span class="line">- (AVCaptureTorchMode)torchMode &#123;</span><br><span class="line">    return [[self activeCamera] torchMode];</span><br><span class="line">&#125;</span><br><span class="line">- (void)setTorchMode:(AVCaptureTorchMode)torchMode &#123;</span><br><span class="line">    AVCaptureDevice *device = [self activeCamera];</span><br><span class="line">    if (device.torchMode != torchMode &amp;&amp;</span><br><span class="line">        [device isTorchModeSupported:torchMode]) &#123;</span><br><span class="line">        NSError *error;</span><br><span class="line">        if ([device lockForConfiguration:&amp;error]) &#123;</span><br><span class="line">            device.torchMode = torchMode;</span><br><span class="line">            [device unlockForConfiguration];</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            [self.delegate deviceConfigurationFailedWithError:error];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>对焦<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">- (BOOL)cameraSupportsTapToFocus &#123;                                          // 1</span><br><span class="line">    return [[self activeCamera] isFocusPointOfInterestSupported];</span><br><span class="line">&#125;</span><br><span class="line">- (void)focusAtPoint:(CGPoint)point &#123;                                       // 2</span><br><span class="line">    AVCaptureDevice *device = [self activeCamera];</span><br><span class="line">    if (device.isFocusPointOfInterestSupported &amp;&amp;                           // 3</span><br><span class="line">        [device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) &#123;</span><br><span class="line">        NSError *error;</span><br><span class="line">        if ([device lockForConfiguration:&amp;error]) &#123;                         // 4</span><br><span class="line">            device.focusPointOfInterest = point;</span><br><span class="line">            device.focusMode = AVCaptureFocusModeAutoFocus;</span><br><span class="line">            [device unlockForConfiguration];</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            [self.delegate deviceConfigurationFailedWithError:error];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>曝光<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">- (BOOL)cameraSupportsTapToExpose &#123;                                         // 1</span><br><span class="line">    return [[self activeCamera] isExposurePointOfInterestSupported];</span><br><span class="line">&#125;</span><br><span class="line">// Define KVO context pointer for observing &apos;adjustingExposure&quot; device property.</span><br><span class="line">static const NSString *THCameraAdjustingExposureContext;</span><br><span class="line">- (void)exposeAtPoint:(CGPoint)point &#123;</span><br><span class="line">    AVCaptureDevice *device = [self activeCamera];</span><br><span class="line">    AVCaptureExposureMode exposureMode =</span><br><span class="line">    AVCaptureExposureModeContinuousAutoExposure;</span><br><span class="line">    if (device.isExposurePointOfInterestSupported &amp;&amp;                        // 2</span><br><span class="line">        [device isExposureModeSupported:exposureMode]) &#123;</span><br><span class="line">        NSError *error;</span><br><span class="line">        if ([device lockForConfiguration:&amp;error]) &#123;                         // 3</span><br><span class="line">            device.exposurePointOfInterest = point;</span><br><span class="line">            device.exposureMode = exposureMode;</span><br><span class="line">            if ([device isExposureModeSupported:AVCaptureExposureModeLocked]) &#123;</span><br><span class="line">                [device addObserver:self                                    // 4</span><br><span class="line">                         forKeyPath:@&quot;adjustingExposure&quot;</span><br><span class="line">                            options:NSKeyValueObservingOptionNew</span><br><span class="line">                            context:&amp;THCameraAdjustingExposureContext];</span><br><span class="line">            &#125;</span><br><span class="line">            [device unlockForConfiguration];</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            [self.delegate deviceConfigurationFailedWithError:error];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">- (void)observeValueForKeyPath:(NSString *)keyPath</span><br><span class="line">                      ofObject:(id)object</span><br><span class="line">                        change:(NSDictionary *)change</span><br><span class="line">                       context:(void *)context &#123;</span><br><span class="line">    if (context == &amp;THCameraAdjustingExposureContext) &#123;                     // 5</span><br><span class="line">        AVCaptureDevice *device = (AVCaptureDevice *)object;</span><br><span class="line">        if (!device.isAdjustingExposure &amp;&amp;                                  // 6</span><br><span class="line">            [device isExposureModeSupported:AVCaptureExposureModeLocked]) &#123;</span><br><span class="line">            [object removeObserver:self                                    // 7</span><br><span class="line">                        forKeyPath:@&quot;adjustingExposure&quot;</span><br><span class="line">                           context:&amp;THCameraAdjustingExposureContext];</span><br><span class="line">            dispatch_async(dispatch_get_main_queue(), ^&#123;                    // 8</span><br><span class="line">                NSError *error;</span><br><span class="line">                if ([device lockForConfiguration:&amp;error]) &#123;</span><br><span class="line">                    device.exposureMode = AVCaptureExposureModeLocked;</span><br><span class="line">                    [device unlockForConfiguration];</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    [self.delegate deviceConfigurationFailedWithError:error];</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        [super observeValueForKeyPath:keyPath</span><br><span class="line">                             ofObject:object</span><br><span class="line">                               change:change</span><br><span class="line">                              context:context];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>AVCaptureStillImageOutput生成图片并保存<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">- (void)captureStillImage &#123;</span><br><span class="line">    AVCaptureConnection *connection =                                   </span><br><span class="line">        [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];</span><br><span class="line">    if (connection.isVideoOrientationSupported) &#123;                       </span><br><span class="line">        connection.videoOrientation = [self currentVideoOrientation];</span><br><span class="line">    &#125;</span><br><span class="line">    id handler = ^(CMSampleBufferRef sampleBuffer, NSError *error) &#123;</span><br><span class="line">        if (sampleBuffer != NULL) &#123;</span><br><span class="line">            NSData *imageData =</span><br><span class="line">                [AVCaptureStillImageOutput</span><br><span class="line">                    jpegStillImageNSDataRepresentation:sampleBuffer];</span><br><span class="line">            UIImage *image = [[UIImage alloc] initWithData:imageData];</span><br><span class="line">            [self writeImageToAssetsLibrary:image];                         // 1</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            NSLog(@&quot;NULL sampleBuffer: %@&quot;, [error localizedDescription]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    // Capture still image</span><br><span class="line">    [self.imageOutput captureStillImageAsynchronouslyFromConnection:connection</span><br><span class="line">                                                  completionHandler:handler];</span><br><span class="line">&#125;</span><br><span class="line">- (void)writeImageToAssetsLibrary:(UIImage *)image &#123;</span><br><span class="line">    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];              // 2</span><br><span class="line">    [library writeImageToSavedPhotosAlbum:image.CGImage                    // 3</span><br><span class="line">                              orientation:(NSInteger)image.imageOrientation // 4</span><br><span class="line">                          completionBlock:^(NSURL *assetURL, NSError *error) &#123;</span><br><span class="line">                              if (!error) &#123;</span><br><span class="line">                                  [self postThumbnailNotifification:image]; // 5</span><br><span class="line">                              &#125; else &#123;</span><br><span class="line">                                  id message = [error localizedDescription];</span><br><span class="line">                                  NSLog(@&quot;Error: %@&quot;, message);</span><br><span class="line">                              &#125;</span><br><span class="line">                          &#125;];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>AVCaptureMovieFileOutput生成文件并保存<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">/开始录制</span><br><span class="line">[self.movieOutput startRecordingToOutputFileURL:self.outputURL recordingDelegate:self];</span><br><span class="line"></span><br><span class="line">//停止录制</span><br><span class="line">[self.movieOutput stopRecording];</span><br><span class="line"></span><br><span class="line">#pragma mark - AVCaptureFileOutputRecordingDelegate - --</span><br><span class="line">- (void)captureOutput:(AVCaptureFileOutput *)captureOutput</span><br><span class="line">didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL</span><br><span class="line">      fromConnections:(NSArray *)connections</span><br><span class="line">                error:(NSError *)error &#123;</span><br><span class="line"> 	if (error) &#123;                                                            // 1</span><br><span class="line">        [self.delegate mediaCaptureFailedWithError:error];</span><br><span class="line"> 	&#125; else &#123;</span><br><span class="line">        [self writeVideoToAssetsLibrary:[self.outputURL copy]];</span><br><span class="line"> 	&#125;</span><br><span class="line">    self.outputURL = nil;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (void)writeVideoToAssetsLibrary:(NSURL *)videoURL &#123;</span><br><span class="line">    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];              // 2</span><br><span class="line">    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:videoURL]) &#123;   // 3</span><br><span class="line">        ALAssetsLibraryWriteVideoCompletionBlock completionBlock;</span><br><span class="line">        completionBlock = ^(NSURL *assetURL, NSError *error)&#123;               // 4</span><br><span class="line">            if (error) &#123;</span><br><span class="line">                [self.delegate assetLibraryWriteFailedWithError:error];</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                [self generateThumbnailForVideoAtURL:videoURL];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        [library writeVideoAtPathToSavedPhotosAlbum:videoURL                // 8</span><br><span class="line">                                    completionBlock:completionBlock];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>


                
            </div>

            <!-- Comments -->
            
                <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                    


                </div>
            
        </div>
    </div>
</article>

    <!-- Footer -->
    <hr>

<!-- Footer -->
<footer>
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <ul class="list-inline text-center">
                    

                    

                    
                        <li>
                            <a href="https://github.com/klugjo/hexo-theme-clean-blog" target="_blank">
                                <span class="fa-stack fa-lg">
                                    <i class="fa fa-circle fa-stack-2x"></i>
                                    <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                                </span>
                            </a>
                        </li>
                    

                    

                    

                    
                </ul>
                <p class="copyright text-muted">&copy; 2020 Cyrus<br></p>
                <p class="copyright text-muted">Original Theme <a target="_blank" href="http://startbootstrap.com/template-overviews/clean-blog/">Clean Blog</a> from <a href="http://startbootstrap.com/" target="_blank">Start Bootstrap</a></p>
                <p class="copyright text-muted">Adapted for <a target="_blank" href="https://hexo.io/">Hexo</a> by <a href="http://www.codeblocq.com/" target="_blank">Jonathan Klughertz</a></p>
                <p class="copyright text-muted"><a href="http://www.beian.miit.gov.cn">粤ICP备18110122号-1</a></p>
            </div>
        </div>
    </div>
</footer>


    <!-- After footer scripts -->
    
<!-- jQuery -->
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>

<!-- Bootstrap -->
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>

<!-- Gallery -->
<script src="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.js" type="text/javascript" charset="utf-8"></script>

<!-- Disqus Comments -->



</body>

</html>